{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# How to use tools\n",
    "\n",
    ":::info Prerequisites\n",
    "\n",
    "This guide assumes familiarity with the following:\n",
    "\n",
    "- [Chatbots](/docs/tutorials/chatbot)\n",
    "- [Tools](/docs/concepts#tools)\n",
    "\n",
    ":::\n",
    "\n",
    "This section will cover how to create conversational agents: chatbots that can interact with other systems and APIs using tools.\n",
    "\n",
    "## Setup\n",
    "\n",
    "For this guide, we’ll be using an OpenAI tools agent with a single tool for searching the web. The default will be powered by [Tavily](/docs/integrations/tools/tavily_search), but you can switch it out for any similar tool. The rest of this section will assume you’re using Tavily.\n",
    "\n",
    "You’ll need to [sign up for an account on the Tavily website](https://tavily.com), and install the following packages:\n",
    "\n",
    "\n",
    "```{=mdx}\n",
    "import Npm2Yarn from \"@theme/Npm2Yarn\";\n",
    "\n",
    "<Npm2Yarn>\n",
    "  @langchain/core @langchain/openai langchain\n",
    "</Npm2Yarn>\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import { TavilySearchResults } from \"@langchain/community/tools/tavily_search\";\n",
    "import { ChatOpenAI } from \"@langchain/openai\";\n",
    "\n",
    "const tools = [\n",
    "  new TavilySearchResults({\n",
    "    maxResults: 1,\n",
    "  }),\n",
    "];\n",
    "\n",
    "const llm = new ChatOpenAI({\n",
    "  model: \"gpt-3.5-turbo-1106\",\n",
    "  temperature: 0,\n",
    "});"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To make our agent conversational, we must also choose a prompt with a placeholder for our chat history. Here’s an example:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import {\n",
    "  ChatPromptTemplate,\n",
    "} from \"@langchain/core/prompts\";\n",
    "\n",
    "// Adapted from https://smith.langchain.com/hub/hwchase17/openai-tools-agent\n",
    "const prompt = ChatPromptTemplate.fromMessages([\n",
    "  [\n",
    "    \"system\",\n",
    "    \"You are a helpful assistant. You may not need to use tools for every query - the user may just want to chat!\",\n",
    "  ],\n",
    "  [\"placeholder\", \"{messages}\"],\n",
    "  [\"placeholder\", \"{agent_scratchpad}\"],\n",
    "]);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Great! Now let’s assemble our agent:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import { AgentExecutor, createOpenAIToolsAgent } from \"langchain/agents\";\n",
    "\n",
    "const agent = await createOpenAIToolsAgent({\n",
    "  llm,\n",
    "  tools,\n",
    "  prompt,\n",
    "});\n",
    "\n",
    "const agentExecutor = new AgentExecutor({ agent, tools });"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Running the agent\n",
    "\n",
    "Now that we’ve set up our agent, let’s try interacting with it! It can handle both trivial queries that require no lookup:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{\n",
       "  messages: [\n",
       "    HumanMessage {\n",
       "      lc_serializable: \u001b[33mtrue\u001b[39m,\n",
       "      lc_kwargs: {\n",
       "        content: \u001b[32m\"I'm Nemo!\"\u001b[39m,\n",
       "        additional_kwargs: {},\n",
       "        response_metadata: {}\n",
       "      },\n",
       "      lc_namespace: [ \u001b[32m\"langchain_core\"\u001b[39m, \u001b[32m\"messages\"\u001b[39m ],\n",
       "      content: \u001b[32m\"I'm Nemo!\"\u001b[39m,\n",
       "      name: \u001b[90mundefined\u001b[39m,\n",
       "      additional_kwargs: {},\n",
       "      response_metadata: {}\n",
       "    }\n",
       "  ],\n",
       "  output: \u001b[32m\"Hello Nemo! It's great to meet you. How can I assist you today?\"\u001b[39m\n",
       "}"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import { HumanMessage } from \"@langchain/core/messages\";\n",
    "\n",
    "await agentExecutor.invoke({\n",
    "  messages: [new HumanMessage(\"I'm Nemo!\")],\n",
    "});"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Or, it can use of the passed search tool to get up to date information if needed:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{\n",
       "  messages: [\n",
       "    HumanMessage {\n",
       "      lc_serializable: \u001b[33mtrue\u001b[39m,\n",
       "      lc_kwargs: {\n",
       "        content: \u001b[32m\"What is the current conservation status of the Great Barrier Reef?\"\u001b[39m,\n",
       "        additional_kwargs: {},\n",
       "        response_metadata: {}\n",
       "      },\n",
       "      lc_namespace: [ \u001b[32m\"langchain_core\"\u001b[39m, \u001b[32m\"messages\"\u001b[39m ],\n",
       "      content: \u001b[32m\"What is the current conservation status of the Great Barrier Reef?\"\u001b[39m,\n",
       "      name: \u001b[90mundefined\u001b[39m,\n",
       "      additional_kwargs: {},\n",
       "      response_metadata: {}\n",
       "    }\n",
       "  ],\n",
       "  output: \u001b[32m\"The current conservation status of the Great Barrier Reef is a cause for concern. The International \"\u001b[39m... 801 more characters\n",
       "}"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "await agentExecutor.invoke({\n",
    "  messages: [\n",
    "    new HumanMessage(\n",
    "      \"What is the current conservation status of the Great Barrier Reef?\"\n",
    "    ),\n",
    "  ],\n",
    "});"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conversational responses\n",
    "\n",
    "Because our prompt contains a placeholder for chat history messages, our agent can also take previous interactions into account and respond conversationally like a standard chatbot:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{\n",
       "  messages: [\n",
       "    HumanMessage {\n",
       "      lc_serializable: \u001b[33mtrue\u001b[39m,\n",
       "      lc_kwargs: {\n",
       "        content: \u001b[32m\"I'm Nemo!\"\u001b[39m,\n",
       "        additional_kwargs: {},\n",
       "        response_metadata: {}\n",
       "      },\n",
       "      lc_namespace: [ \u001b[32m\"langchain_core\"\u001b[39m, \u001b[32m\"messages\"\u001b[39m ],\n",
       "      content: \u001b[32m\"I'm Nemo!\"\u001b[39m,\n",
       "      name: \u001b[90mundefined\u001b[39m,\n",
       "      additional_kwargs: {},\n",
       "      response_metadata: {}\n",
       "    },\n",
       "    AIMessage {\n",
       "      lc_serializable: \u001b[33mtrue\u001b[39m,\n",
       "      lc_kwargs: {\n",
       "        content: \u001b[32m\"Hello Nemo! How can I assist you today?\"\u001b[39m,\n",
       "        tool_calls: [],\n",
       "        invalid_tool_calls: [],\n",
       "        additional_kwargs: {},\n",
       "        response_metadata: {}\n",
       "      },\n",
       "      lc_namespace: [ \u001b[32m\"langchain_core\"\u001b[39m, \u001b[32m\"messages\"\u001b[39m ],\n",
       "      content: \u001b[32m\"Hello Nemo! How can I assist you today?\"\u001b[39m,\n",
       "      name: \u001b[90mundefined\u001b[39m,\n",
       "      additional_kwargs: {},\n",
       "      response_metadata: {},\n",
       "      tool_calls: [],\n",
       "      invalid_tool_calls: []\n",
       "    },\n",
       "    HumanMessage {\n",
       "      lc_serializable: \u001b[33mtrue\u001b[39m,\n",
       "      lc_kwargs: {\n",
       "        content: \u001b[32m\"What is my name?\"\u001b[39m,\n",
       "        additional_kwargs: {},\n",
       "        response_metadata: {}\n",
       "      },\n",
       "      lc_namespace: [ \u001b[32m\"langchain_core\"\u001b[39m, \u001b[32m\"messages\"\u001b[39m ],\n",
       "      content: \u001b[32m\"What is my name?\"\u001b[39m,\n",
       "      name: \u001b[90mundefined\u001b[39m,\n",
       "      additional_kwargs: {},\n",
       "      response_metadata: {}\n",
       "    }\n",
       "  ],\n",
       "  output: \u001b[32m\"Your name is Nemo!\"\u001b[39m\n",
       "}"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import { AIMessage } from \"@langchain/core/messages\";\n",
    "\n",
    "await agentExecutor.invoke({\n",
    "  messages: [\n",
    "    new HumanMessage(\"I'm Nemo!\"),\n",
    "    new AIMessage(\"Hello Nemo! How can I assist you today?\"),\n",
    "    new HumanMessage(\"What is my name?\"),\n",
    "  ],\n",
    "});"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If preferred, you can also wrap the agent executor in a `RunnableWithMessageHistory` class to internally manage history messages. First, we need to slightly modify the prompt to take a separate input variable so that the wrapper can parse which input value to store as history:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "// Adapted from https://smith.langchain.com/hub/hwchase17/openai-tools-agent\n",
    "const prompt2 = ChatPromptTemplate.fromMessages([\n",
    "  [\n",
    "    \"system\",\n",
    "    \"You are a helpful assistant. You may not need to use tools for every query - the user may just want to chat!\",\n",
    "  ],\n",
    "  [\"placeholder\", \"{chat_history}\"],\n",
    "  [\"human\", \"{input}\"],\n",
    "  [\"placeholder\", \"{agent_scratchpad}\"],\n",
    "]);\n",
    "\n",
    "const agent2 = await createOpenAIToolsAgent({\n",
    "  llm,\n",
    "  tools,\n",
    "  prompt: prompt2,\n",
    "});\n",
    "\n",
    "const agentExecutor2 = new AgentExecutor({ agent: agent2, tools });"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then, because our agent executor has multiple outputs, we also have to set the `outputMessagesKey` property when initializing the wrapper:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "import { ChatMessageHistory } from \"langchain/stores/message/in_memory\";\n",
    "import { RunnableWithMessageHistory } from \"@langchain/core/runnables\";\n",
    "\n",
    "const demoEphemeralChatMessageHistory = new ChatMessageHistory();\n",
    "\n",
    "const conversationalAgentExecutor = new RunnableWithMessageHistory({\n",
    "  runnable: agentExecutor2,\n",
    "  getMessageHistory: (_sessionId) => demoEphemeralChatMessageHistory,\n",
    "  inputMessagesKey: \"input\",\n",
    "  outputMessagesKey: \"output\",\n",
    "  historyMessagesKey: \"chat_history\",\n",
    "});"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{\n",
       "  input: \u001b[32m\"I'm Nemo!\"\u001b[39m,\n",
       "  chat_history: [\n",
       "    HumanMessage {\n",
       "      lc_serializable: \u001b[33mtrue\u001b[39m,\n",
       "      lc_kwargs: {\n",
       "        content: \u001b[32m\"I'm Nemo!\"\u001b[39m,\n",
       "        additional_kwargs: {},\n",
       "        response_metadata: {}\n",
       "      },\n",
       "      lc_namespace: [ \u001b[32m\"langchain_core\"\u001b[39m, \u001b[32m\"messages\"\u001b[39m ],\n",
       "      content: \u001b[32m\"I'm Nemo!\"\u001b[39m,\n",
       "      name: \u001b[90mundefined\u001b[39m,\n",
       "      additional_kwargs: {},\n",
       "      response_metadata: {}\n",
       "    },\n",
       "    AIMessage {\n",
       "      lc_serializable: \u001b[33mtrue\u001b[39m,\n",
       "      lc_kwargs: {\n",
       "        content: \u001b[32m\"Hello Nemo! It's great to meet you. How can I assist you today?\"\u001b[39m,\n",
       "        tool_calls: [],\n",
       "        invalid_tool_calls: [],\n",
       "        additional_kwargs: {},\n",
       "        response_metadata: {}\n",
       "      },\n",
       "      lc_namespace: [ \u001b[32m\"langchain_core\"\u001b[39m, \u001b[32m\"messages\"\u001b[39m ],\n",
       "      content: \u001b[32m\"Hello Nemo! It's great to meet you. How can I assist you today?\"\u001b[39m,\n",
       "      name: \u001b[90mundefined\u001b[39m,\n",
       "      additional_kwargs: {},\n",
       "      response_metadata: {},\n",
       "      tool_calls: [],\n",
       "      invalid_tool_calls: []\n",
       "    }\n",
       "  ],\n",
       "  output: \u001b[32m\"Hello Nemo! It's great to meet you. How can I assist you today?\"\u001b[39m\n",
       "}"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "await conversationalAgentExecutor.invoke(\n",
    "  { input: \"I'm Nemo!\" },\n",
    "  { configurable: { sessionId: \"unused\" } }\n",
    ");"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{\n",
       "  input: \u001b[32m\"What is my name?\"\u001b[39m,\n",
       "  chat_history: [\n",
       "    HumanMessage {\n",
       "      lc_serializable: \u001b[33mtrue\u001b[39m,\n",
       "      lc_kwargs: {\n",
       "        content: \u001b[32m\"I'm Nemo!\"\u001b[39m,\n",
       "        additional_kwargs: {},\n",
       "        response_metadata: {}\n",
       "      },\n",
       "      lc_namespace: [ \u001b[32m\"langchain_core\"\u001b[39m, \u001b[32m\"messages\"\u001b[39m ],\n",
       "      content: \u001b[32m\"I'm Nemo!\"\u001b[39m,\n",
       "      name: \u001b[90mundefined\u001b[39m,\n",
       "      additional_kwargs: {},\n",
       "      response_metadata: {}\n",
       "    },\n",
       "    AIMessage {\n",
       "      lc_serializable: \u001b[33mtrue\u001b[39m,\n",
       "      lc_kwargs: {\n",
       "        content: \u001b[32m\"Hello Nemo! It's great to meet you. How can I assist you today?\"\u001b[39m,\n",
       "        tool_calls: [],\n",
       "        invalid_tool_calls: [],\n",
       "        additional_kwargs: {},\n",
       "        response_metadata: {}\n",
       "      },\n",
       "      lc_namespace: [ \u001b[32m\"langchain_core\"\u001b[39m, \u001b[32m\"messages\"\u001b[39m ],\n",
       "      content: \u001b[32m\"Hello Nemo! It's great to meet you. How can I assist you today?\"\u001b[39m,\n",
       "      name: \u001b[90mundefined\u001b[39m,\n",
       "      additional_kwargs: {},\n",
       "      response_metadata: {},\n",
       "      tool_calls: [],\n",
       "      invalid_tool_calls: []\n",
       "    },\n",
       "    HumanMessage {\n",
       "      lc_serializable: \u001b[33mtrue\u001b[39m,\n",
       "      lc_kwargs: {\n",
       "        content: \u001b[32m\"What is my name?\"\u001b[39m,\n",
       "        additional_kwargs: {},\n",
       "        response_metadata: {}\n",
       "      },\n",
       "      lc_namespace: [ \u001b[32m\"langchain_core\"\u001b[39m, \u001b[32m\"messages\"\u001b[39m ],\n",
       "      content: \u001b[32m\"What is my name?\"\u001b[39m,\n",
       "      name: \u001b[90mundefined\u001b[39m,\n",
       "      additional_kwargs: {},\n",
       "      response_metadata: {}\n",
       "    },\n",
       "    AIMessage {\n",
       "      lc_serializable: \u001b[33mtrue\u001b[39m,\n",
       "      lc_kwargs: {\n",
       "        content: \u001b[32m\"Your name is Nemo!\"\u001b[39m,\n",
       "        tool_calls: [],\n",
       "        invalid_tool_calls: [],\n",
       "        additional_kwargs: {},\n",
       "        response_metadata: {}\n",
       "      },\n",
       "      lc_namespace: [ \u001b[32m\"langchain_core\"\u001b[39m, \u001b[32m\"messages\"\u001b[39m ],\n",
       "      content: \u001b[32m\"Your name is Nemo!\"\u001b[39m,\n",
       "      name: \u001b[90mundefined\u001b[39m,\n",
       "      additional_kwargs: {},\n",
       "      response_metadata: {},\n",
       "      tool_calls: [],\n",
       "      invalid_tool_calls: []\n",
       "    }\n",
       "  ],\n",
       "  output: \u001b[32m\"Your name is Nemo!\"\u001b[39m\n",
       "}"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "await conversationalAgentExecutor.invoke(\n",
    "  { input: \"What is my name?\" },\n",
    "  { configurable: { sessionId: \"unused\" } }\n",
    ");"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Next steps\n",
    "\n",
    "You've now learned how to create chatbots with tool-use capabilities.\n",
    "\n",
    "For more, check out the other guides in this section, including [how to add history to your chatbots](/docs/how_to/chatbots_memory)."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Deno",
   "language": "typescript",
   "name": "deno"
  },
  "language_info": {
   "file_extension": ".ts",
   "mimetype": "text/x.typescript",
   "name": "typescript",
   "nb_converter": "script",
   "pygments_lexer": "typescript",
   "version": "5.3.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
